package com.forestar.mapControl.utils.mapConvert.geometry.utils;


import com.forestar.mapControl.utils.mapConvert.geometry.Envelope;
import com.forestar.mapControl.utils.mapConvert.geometry.GeoLine;
import com.forestar.mapControl.utils.mapConvert.geometry.GeoMultiPoint;
import com.forestar.mapControl.utils.mapConvert.geometry.GeoMultiPolygon;
import com.forestar.mapControl.utils.mapConvert.geometry.GeoPoint;
import com.forestar.mapControl.utils.mapConvert.geometry.GeoPolygon;
import com.forestar.mapControl.utils.mapConvert.geometry.IGeometry;
import com.forestar.mapControl.utils.mapConvert.geometry.coordinatesystem.CoordinateSystem;
import com.forestar.mapControl.utils.mapConvert.geometry.coordinatesystem.GeoTransformer;
import com.mapzone.api.geometry.mzEnvelope;
import com.mapzone.api.geometry.mzGeometry;
import com.mapzone.api.geometry.mzGeometrySet;
import com.mapzone.api.geometry.mzHitInfos;
import com.mapzone.api.geometry.mzMultiLineString;
import com.mapzone.api.geometry.mzMultiPoint;
import com.mapzone.api.geometry.mzMultiPolygon;
import com.mapzone.api.geometry.mzPath;
import com.mapzone.api.geometry.mzPoint;
import com.mapzone.api.geometry.mzPolygon;
import com.mapzone.api.geometry.mzSpatialAnylize;

import java.util.ArrayList;
import java.util.List;

public class SpatialAnylize
  {

    // / <summary>
    // / 最近距离
    // / </summary>
    public final static int DistanceNearest = 1;
    // / <summary>
    // / 最远距离
    // / </summary>
    public final static int DistanceFarest = 2;
    // / <summary>
    // / 平均距离
    // / </summary>
    public final static int DistanceAverage = 3;

    // / <summary>
    // / 检测是否落在对象上（可选中）, 与其他值进行位运算无意义
    // / </summary>
    public final static int HitTestSimple = 0x0001;
    // / <summary>
    // / 是否测试到几何对象的节点上
    // / </summary>
    public final static int HitTestVertex = 0x0002;
    // / <summary>
    // / 是否测试到几何对象的边界上
    // / </summary>
    public final static int HitTestBoundary = 0x0004;

    //容差的默认值
    public final static double DEFAULT_TOLERANCE = 0.000000008983153; //默认的地理坐标容差（和ARCGIS相同）

    /**
     * 获取两个几何的距离
     *
     * @param geometry0 geometry0
     * @param geometry1 geometry1
     * @param type      距离类型,type参数的值：mzDistanceNearest，mzDistanceFarest，mzDistanceAverage
     * @return 两个几何的距离
     */
    public static double Distance(IGeometry geometry0, IGeometry geometry1, int type)
      {
        //进行坐标投影,将两个几何体的坐标系投影到同一个坐标系统
        CoordinateSystem from = geometry0.getCoordinateSystem();
        CoordinateSystem to = geometry1.getCoordinateSystem();
        IGeometry geometry0Clone = geometry0.Clone();
        GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
        transformer.transform(geometry0Clone);
        Object obj0 = geometry0Clone.getInternalObject();
        Object obj1 = geometry1.getInternalObject();
        if ((obj0 instanceof mzGeometry) && (obj1 instanceof mzGeometry))
          {
            return mzSpatialAnylize.Distance((mzGeometry) obj0, (mzGeometry) obj1, type);
          } else
          {
            return 0.0;
          }
      }
    public static double Distance(IGeometry geometry0, GeoPoint geoPoint, int srid ,int type)
      {
        CoordinateSystem coordinateSystemTo = CoordinateSystem.create(srid);
        //两个要素都投影到一个平面坐标上  经纬度时拿到的结果错误
        GeoTransformer transformer1 = CoordinateSystem.getTransformer(geometry0.getCoordinateSystem(), coordinateSystemTo);
        transformer1.transform(geometry0);
        IGeometry geometry0Clone = geometry0.Clone();
        Object obj0 = geometry0Clone.getInternalObject();

        GeoPoint geoPointOut = new GeoPoint(coordinateSystemTo,0,0);
        CoordinateSystem.projectPoint(geoPoint,geoPointOut);
        mzPoint mzPoint = new mzPoint(geoPointOut.getX(),geoPointOut.getY());
        mzPoint.setSrid(geoPointOut.getCoordinateSystem().getSrid());

        if ((obj0 instanceof mzGeometry) && (mzPoint instanceof mzGeometry))
          {
            return mzSpatialAnylize.Distance((mzGeometry) obj0, (mzGeometry) mzPoint, type);
          } else
          {
            return 0.0;
          }
      }
    /**
     * 分割,使用一条线分割当前图形要素，面分割后pResult中所有面一定是单面 或单线
     *
     * @param geo    被分割的几何
     * @param cutter 分割线，必须是一段连续的线,如果有自交则只能有一个自交点
     * @return 分割后的图形结果
     */
    public static List<IGeometry> Cut(IGeometry geo, IGeometry cutter)
      {
        //进行坐标投影，将修边线的坐标系投影到面几何的坐标系
        CoordinateSystem from = cutter.getCoordinateSystem();
        CoordinateSystem to = geo.getCoordinateSystem();
        GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
        transformer.transform(cutter);
        // 1.分割
        Object obj = geo.getInternalObject();
        Object objPath = cutter.getInternalObject();
        mzGeometrySet m_mzGeometrySet = null;
        if ((obj instanceof mzGeometry) && (objPath instanceof mzGeometry))
          {
            mzGeometry m_mzGeometry = (mzGeometry) obj;
            double dTolerance = m_mzGeometry.getTolerance();
            if (objPath instanceof mzPolygon)
              {
                objPath = ((mzPolygon) objPath).GetExteriorRing();
              } else if (objPath instanceof mzMultiPolygon)
              {
                objPath = ((mzMultiPolygon) objPath).GetPolygon(0).GetExteriorRing();
              }
            m_mzGeometrySet = mzSpatialAnylize.Cut((mzGeometry) obj, (mzGeometry) objPath, dTolerance);
          }
        // 2.处理分割结果
        if (m_mzGeometrySet == null)
          {
            return null;
          }
        List<IGeometry> lstIGeoReult = new ArrayList<>();
        int nGeometryCount = m_mzGeometrySet.GetGeometryCount();
        for (int i = 0; i < nGeometryCount; i++)
          {
            mzGeometry m_mzGeometry = m_mzGeometrySet.GetGeometry(i);
            IGeometry geoResult = GeometryUtils.mzGeometry2IGeometry(m_mzGeometry);
            lstIGeoReult.add(geoResult);
          }
        return lstIGeoReult;
      }

    /**
     * 并,当前只允许同类型的几何执行并操作，或点与多点，path与multipath
     *
     * @param geo0 g0
     * @param geo1 g1
     * @return 求并的结果
     */
    public static IGeometry Union(IGeometry geo0, IGeometry geo1)
      {
        //进行坐标投影,将两个几何体的坐标系投影到同一个坐标系统
        CoordinateSystem from = geo0.getCoordinateSystem();
        CoordinateSystem to = geo1.getCoordinateSystem();
        GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
        transformer.transform(geo0);
        IGeometry geoResult = null;
        Object obj0 = geo0.getInternalObject();
        Object obj1 = geo1.getInternalObject();
        if ((obj0 instanceof mzGeometry) && (obj1 instanceof mzGeometry))
          {
            mzGeometry m_mzGeometry0 = (mzGeometry) obj0;
            mzGeometry m_mzGeometry1 = (mzGeometry) obj1;
            double dTolerance = m_mzGeometry0.getTolerance();
            mzGeometry m_mzGeoResult = mzSpatialAnylize.Union(m_mzGeometry0, m_mzGeometry1, dTolerance);
            geoResult = GeometryUtils.mzGeometry2IGeometry(m_mzGeoResult);
          }
        return geoResult;
      }

    /**
     * 交
     *
     * @param geo0 g0
     * @param geo1 g1
     * @return 交的结果可能是点，线，面的任一种，如线线相交，结果就\可以为点，多点，或线，或这三者的组合
     */
    public static List<IGeometry> Intersect(IGeometry geo0, IGeometry geo1)
      {
        List<IGeometry> lstIGeoReult = new ArrayList<IGeometry>();
        //进行坐标投影,将两个几何体的坐标系投影到同一个坐标系统
        CoordinateSystem from = geo0.getCoordinateSystem();
        CoordinateSystem to = geo1.getCoordinateSystem();
        if (from.getSrid() != to.getSrid())
          {
            GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
            transformer.transform(geo0);
          }
        // 1.相交
        Object obj0 = geo0.getInternalObject();
        Object obj1 = geo1.getInternalObject();
        mzGeometrySet m_mzGeometrySet = null;
        if ((obj0 instanceof mzGeometry) && (obj1 instanceof mzGeometry))
          {
            mzGeometry m_mzGeometry0 = (mzGeometry) obj0;
            mzGeometry m_mzGeometry1 = (mzGeometry) obj1;
            double dTolerance = m_mzGeometry0.getTolerance();
            m_mzGeometrySet = mzSpatialAnylize.Intersect(m_mzGeometry0, m_mzGeometry1, dTolerance);
          }
        // 2.处理相交的结果
        if (m_mzGeometrySet == null)
          return lstIGeoReult;
        int nGeometryCount = m_mzGeometrySet.GetGeometryCount();
        for (int i = 0; i < nGeometryCount; i++)
          {
            mzGeometry m_mzGeometry = m_mzGeometrySet.GetGeometry(i);
            IGeometry geoResult = GeometryUtils.mzGeometry2IGeometry(m_mzGeometry);
            lstIGeoReult.add(geoResult);
          }
        return lstIGeoReult;
      }

    /**
     * 差,g0差g1
     *
     * @param geo0 g0
     * @param geo1 g1
     * @return 求差的结果
     */
    public static IGeometry Difference(IGeometry geo0, IGeometry geo1)
      {
        //进行坐标投影,将两个几何体的坐标系投影到同一个坐标系统
        CoordinateSystem from = geo0.getCoordinateSystem();
        CoordinateSystem to = geo1.getCoordinateSystem();
        if (from.getSrid() != to.getSrid())
          {
            GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
            transformer.transform(geo0);
          }
        // 1.差
        Object obj0 = geo0.getInternalObject();
        Object obj1 = geo1.getInternalObject();
        IGeometry geoResult = null;
        if ((obj0 instanceof mzGeometry) && (obj1 instanceof mzGeometry))
          {
            mzGeometry m_mzGeo0 = (mzGeometry) obj0;
            mzGeometry m_mzGeo1 = (mzGeometry) obj1;
            double dTolerance = m_mzGeo0.getTolerance();
            mzGeometry m_mzGeoResult = mzSpatialAnylize.Difference(m_mzGeo0, m_mzGeo1, dTolerance);
            geoResult = GeometryUtils.mzGeometry2IGeometry(m_mzGeoResult);
          }
        return geoResult;
      }

    //多个面几何求交（只能针对面求交）
    public static IGeometry PolygonTopoIntersect(List<IGeometry> lstGeoSet)
      {
        //1)进行坐标投影,将所有几何体的坐标系投影到同一个坐标系统
        CoordinateSystem from = null;
        CoordinateSystem to = null;
        if (lstGeoSet.size() > 0)
          {
            to = lstGeoSet.get(0).getCoordinateSystem();
          } else
          {
            return null;
          }
        for (int i = 0; i < lstGeoSet.size(); i++)
          {
            IGeometry geo = lstGeoSet.get(i);
            from = geo.getCoordinateSystem();
            GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
            transformer.transform(geo);
          }
        //2)进行求交操作
        //默认容差（1毫米）
        double tolerance = DEFAULT_TOLERANCE;
        mzGeometrySet pGeoSet = new mzGeometrySet(true);
        for (int i = 0; i < lstGeoSet.size(); i++)
          {
            Object objGeo = lstGeoSet.get(i).getInternalObject();
            if (objGeo instanceof mzGeometry)
              {
                mzGeometry pGeo = (mzGeometry) objGeo;
                tolerance = pGeo.getTolerance();
                //克隆几何，底层创建的所有操作，不会影响传入的几何体
                mzGeometry pGeoClone = pGeo.clone();
                pGeoSet.AddGeometry(pGeoClone);
              }
          }
        mzGeometry m_mzGeoResult = mzSpatialAnylize.PolygonTopoIntersect(pGeoSet, tolerance);
        IGeometry geoResult = GeometryUtils.mzGeometry2IGeometry(m_mzGeoResult);
        return geoResult;
      }

    //多个面几何求并（只能针对面求并）
    public static IGeometry PolygonTopoUnion(List<IGeometry> lstGeoSet)
      {
        //1)进行坐标投影,将所有几何体的坐标系投影到同一个坐标系统
        CoordinateSystem from = null;
        CoordinateSystem to = null;
        if (lstGeoSet.size() > 0)
          {
            to = lstGeoSet.get(0).getCoordinateSystem();
          } else
          {
            return null;
          }
        for (int i = 0; i < lstGeoSet.size(); i++)
          {
            IGeometry geo = lstGeoSet.get(i);
            from = geo.getCoordinateSystem();
            GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
            transformer.transform(geo);
          }
        //2)进行求并操作
        //默认容差（1毫米）
        double tolerance = DEFAULT_TOLERANCE;
        mzGeometrySet pGeoSet = new mzGeometrySet(true);
        for (int i = 0; i < lstGeoSet.size(); i++)
          {
            Object objGeo = lstGeoSet.get(i).getInternalObject();
            if (objGeo instanceof mzGeometry)
              {
                mzGeometry pGeo = (mzGeometry) objGeo;
                tolerance = pGeo.getTolerance();
                //克隆几何，底层创建的所有操作，不会影响传入的几何体
                mzGeometry pGeoClone = pGeo.clone();
                pGeoSet.AddGeometry(pGeoClone);
              }
          }
        mzGeometry m_mzGeoResult = mzSpatialAnylize.PolygonTopoUnion(pGeoSet, tolerance);
        IGeometry geoResult = GeometryUtils.mzGeometry2IGeometry(m_mzGeoResult);
        return geoResult;
      }

    //多个面几何相减（只能针对面相减）
    public static IGeometry PolygonTopoDifference(List<IGeometry> lstGeoSet0, List<IGeometry> lstGeoSet1)
      {
        //1)进行坐标投影,将所有几何体的坐标系投影到同一个坐标系统
        CoordinateSystem from = null;
        CoordinateSystem to = null;
        if (lstGeoSet0.size() > 0)
          {
            to = lstGeoSet0.get(0).getCoordinateSystem();
          } else if (lstGeoSet1.size() > 0)
          {
            to = lstGeoSet1.get(0).getCoordinateSystem();
          } else
          {
            return null;
          }
        for (int i = 0; i < lstGeoSet0.size(); i++)
          {
            IGeometry geo = lstGeoSet0.get(i);
            from = geo.getCoordinateSystem();
            GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
            transformer.transform(geo);
          }
        for (int i = 0; i < lstGeoSet1.size(); i++)
          {
            IGeometry geo = lstGeoSet1.get(i);
            from = geo.getCoordinateSystem();
            GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
            transformer.transform(geo);
          }
        //2)进行相减操作
        //默认容差（1毫米）
        double tolerance = DEFAULT_TOLERANCE;
        mzGeometrySet pGeoSet0 = new mzGeometrySet(true);
        mzGeometrySet pGeoSet1 = new mzGeometrySet(true);
        for (int i = 0; i < lstGeoSet0.size(); i++)
          {
            Object objGeo = lstGeoSet0.get(i).getInternalObject();
            if (objGeo instanceof mzGeometry)
              {
                mzGeometry pGeo = (mzGeometry) objGeo;
                tolerance = pGeo.getTolerance();
                //克隆几何，底层创建的所有操作，不会影响传入的几何体
                mzGeometry pGeoClone = pGeo.clone();
                pGeoSet0.AddGeometry(pGeoClone);
              }
          }
        for (int i = 0; i < lstGeoSet1.size(); i++)
          {
            Object objGeo = lstGeoSet1.get(i).getInternalObject();
            if (objGeo instanceof mzGeometry)
              {
                mzGeometry pGeo = (mzGeometry) objGeo;
                //克隆几何，底层创建的所有操作，不会影响传入的几何体
                mzGeometry pGeoClone = pGeo.clone();
                pGeoSet1.AddGeometry(pGeoClone);
              }
          }
        mzGeometry m_mzGeoResult = mzSpatialAnylize.PolygonTopoDifference(pGeoSet0, pGeoSet1, tolerance);
        IGeometry geoResult = GeometryUtils.mzGeometry2IGeometry(m_mzGeoResult);
        return geoResult;
      }

    /**
     * 两个图形是否相等,如果两个图形位置完全一致，返回true，否则返回false
     *
     * @param geo0 g0
     * @param geo1 g1
     * @return 是否位置完全一致，是返回true，否则返回false
     */
    public static boolean IsEquals(IGeometry geo0, IGeometry geo1)
      {
        //进行坐标投影,将两个几何体的坐标系投影到同一个坐标系统
        CoordinateSystem from = geo0.getCoordinateSystem();
        CoordinateSystem to = geo1.getCoordinateSystem();
        IGeometry geoClone = geo0.Clone();
        GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
        transformer.transform(geoClone);
        // 1.是否相等
        boolean isEquals = false;
        Object obj0 = geoClone.getInternalObject();
        Object obj1 = geo1.getInternalObject();
        if ((obj0 instanceof mzGeometry) && (obj1 instanceof mzGeometry))
          {
            mzGeometry m_mzGeo0 = (mzGeometry) obj0;
            mzGeometry m_mzGeo1 = (mzGeometry) obj1;
            double dTolerance = m_mzGeo0.getTolerance();
            isEquals = mzSpatialAnylize.IsEquals(m_mzGeo0, m_mzGeo1, dTolerance);
          }
        return isEquals;
      }

    /**
     * 是否有交
     *
     * @param geo0 g0
     * @param geo1 g1
     * @return 有交返回TRUE，无交返回FALSE
     */
    public static boolean IsIntersect(IGeometry geo0, IGeometry geo1)
      {
        //进行坐标投影,将两个几何体的坐标系投影到同一个坐标系统
        CoordinateSystem from = geo0.getCoordinateSystem();
        CoordinateSystem to = geo1.getCoordinateSystem();
        IGeometry geoClone = geo0.Clone();
        GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
        transformer.transform(geoClone);
        boolean isIntersect = false;
        Object obj0 = geoClone.getInternalObject();
        Object obj1 = geo1.getInternalObject();
        if ((obj0 instanceof mzGeometry) && (obj1 instanceof mzGeometry))
          {
            mzGeometry m_mzGeometry0 = (mzGeometry) obj0;
            mzGeometry m_mzGeometry1 = (mzGeometry) obj1;
            double dTolerance = m_mzGeometry0.getTolerance();
            isIntersect = mzSpatialAnylize.IsIntersect(m_mzGeometry0, m_mzGeometry1, dTolerance);
          }
        return isIntersect;
      }

    public static boolean IsIntersect(IGeometry geo, Envelope env)
      {
        //进行坐标投影,将两个几何体的坐标系投影到同一个坐标系统
        CoordinateSystem from = geo.getCoordinateSystem();
        CoordinateSystem to = env.getCoordinateSystem();
        IGeometry geoClone = geo.Clone();
        GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
        transformer.transform(geoClone);
        boolean isIntersect = false;
        Object obj = geoClone.getInternalObject();
        mzEnvelope mzenv = new mzEnvelope(env.getXMin(), env.getYMax(), env.getXMax(), env.getYMin());
        mzenv.setSrid(env.getCoordinateSystem().getSrid());
        if (obj instanceof mzGeometry)
          {
            mzGeometry m_mzGeo = (mzGeometry) obj;
            double dTolerance = m_mzGeo.getTolerance();
            isIntersect = mzSpatialAnylize.IsIntersect(m_mzGeo, mzenv, dTolerance);
          }
        return isIntersect;
      }

    /**
     * 是否包含
     *
     * @param env  env
     * @param geo0 g0
     * @return 如果g0包含g1返回TRUE，否则返回FALSE
     */
    public static boolean IsContains(Envelope env, IGeometry geo0)
      {
        //1)进行坐标投影,将两个几何体的坐标系投影到同一个坐标系统
        CoordinateSystem from = geo0.getCoordinateSystem();
        CoordinateSystem to = env.getCoordinateSystem();
        IGeometry geoClone = geo0.Clone();
        GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
        transformer.transform(geoClone);
        //2）进行包含操作
        boolean isContains = false;
        Object obj0 = geoClone.getInternalObject();
        mzEnvelope mzenv = new mzEnvelope(env.getXMin(), env.getYMax(), env.getXMax(), env.getYMin());
        mzenv.setSrid(env.getCoordinateSystem().getSrid());
        if ((obj0 instanceof mzGeometry) && (mzenv instanceof mzGeometry))
          {
            mzGeometry m_mzGeometry0 = (mzGeometry) mzenv;
            mzGeometry m_mzGeometry1 = (mzGeometry) obj0;
            double dTolerance = m_mzGeometry0.getTolerance();
            isContains = mzSpatialAnylize.IsContains(m_mzGeometry0, m_mzGeometry1, dTolerance);
          }
        return isContains;
      }

    /**
     * 是否包含
     *
     * @param geo0 g0
     * @param geo1 g1
     * @return 如果g0包含g1返回TRUE，否则返回FALSE
     */
    public static boolean IsContains(IGeometry geo0, IGeometry geo1)
      {
        //1)进行坐标投影,将两个几何体的坐标系投影到同一个坐标系统
        CoordinateSystem from = geo0.getCoordinateSystem();
        CoordinateSystem to = geo1.getCoordinateSystem();
        IGeometry geoClone = geo0.Clone();
        if (from.getSrid() != to.getSrid())
          {
            GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
            transformer.transform(geoClone);
          }
        //2）进行包含操作
        boolean isContains = false;
        Object obj0 = geoClone.getInternalObject();
        Object obj1 = geo1.getInternalObject();
        if ((obj0 instanceof mzGeometry) && (obj1 instanceof mzGeometry))
          {
            mzGeometry m_mzGeometry0 = (mzGeometry) obj0;
            mzGeometry m_mzGeometry1 = (mzGeometry) obj1;
            double dTolerance = m_mzGeometry0.getTolerance();
            isContains = mzSpatialAnylize.IsContains(m_mzGeometry0, m_mzGeometry1, dTolerance);
          }
        return isContains;
      }

    public static boolean IsContains(IGeometry geo0, GeoPoint geoPoint)
      {
        //1)进行坐标投影,将两个几何体的坐标系投影到同一个坐标系统
        CoordinateSystem from = geo0.getCoordinateSystem();
        CoordinateSystem to = geoPoint.getCoordinateSystem();
        IGeometry geoClone = geo0.Clone();
        if (from.getSrid() != to.getSrid())
          {
            GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
            transformer.transform(geoClone);
          }
        //2）进行包含操作
        boolean isContains = false;
        Object obj0 = geoClone.getInternalObject();
        mzPoint mzPoint = new mzPoint(geoPoint.getX(),geoPoint.getY());
        mzPoint.setSrid(geoPoint.getCoordinateSystem().getSrid());
        if ((obj0 instanceof mzGeometry) && (mzPoint instanceof mzGeometry))
          {
            mzGeometry m_mzGeometry0 = (mzGeometry) obj0;
            mzGeometry m_mzGeometry1 = (mzGeometry) mzPoint;
            double dTolerance = m_mzGeometry0.getTolerance();
            isContains = mzSpatialAnylize.IsContains(m_mzGeometry0, m_mzGeometry1, dTolerance);
          }
        return isContains;
      }


    /**
     * 是否相离,g0是否与g1相离
     *
     * @param geo0 g0
     * @param geo1 g1
     * @return 如果相离返回TRUE，否则返回FALSE
     */
    public static boolean IsDisjoint(IGeometry geo0, IGeometry geo1)
      {
        //1)进行坐标投影,将两个几何体的坐标系投影到同一个坐标系统
        CoordinateSystem from = geo0.getCoordinateSystem();
        CoordinateSystem to = geo1.getCoordinateSystem();
        IGeometry geoClone = geo0.Clone();
        GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
        transformer.transform(geoClone);
        //2)进行向离判断操作
        boolean isDisjoint = false;
        Object obj0 = geoClone.getInternalObject();
        Object obj1 = geo1.getInternalObject();
        if ((obj0 instanceof mzGeometry) && (obj1 instanceof mzGeometry))
          {
            mzGeometry m_mzGeometry0 = (mzGeometry) obj0;
            mzGeometry m_mzGeometry1 = (mzGeometry) obj1;
            double dTolerance = m_mzGeometry0.getTolerance();
            isDisjoint = mzSpatialAnylize.IsDisjoint(m_mzGeometry0, m_mzGeometry1, dTolerance);
          }
        return isDisjoint;
      }

    /**
     * 是否相接,返回两个图形是否相切
     *
     * @param geo0 g0
     * @param geo1 g1
     * @return 如果相接返回TRUE，否则返回FALSE
     */
    public static boolean IsTouches(IGeometry geo0, IGeometry geo1)
      {
        //1)进行坐标投影,将两个几何体的坐标系投影到同一个坐标系统
        CoordinateSystem from = geo0.getCoordinateSystem();
        CoordinateSystem to = geo1.getCoordinateSystem();
        IGeometry geoClone = geo0.Clone();
        GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
        transformer.transform(geoClone);
        //2)进行isTouches判断
        boolean isTouches = false;
        Object obj0 = geoClone.getInternalObject();
        Object obj1 = geo1.getInternalObject();
        if ((obj0 instanceof mzGeometry) && (obj1 instanceof mzGeometry))
          {
            mzGeometry m_mzGeometry0 = (mzGeometry) obj0;
            mzGeometry m_mzGeometry1 = (mzGeometry) obj1;
            double dTolerance = m_mzGeometry0.getTolerance();
            isTouches = mzSpatialAnylize.IsTouches(m_mzGeometry0, m_mzGeometry1, dTolerance);
          }
        return isTouches;
      }

    /**
     * 是否穿越(几何对象共享一些但不是所有内部点。) 1)g0是否穿越g1 2)两条线穿越说明这两条线有公共点，且至少一个点不是线的端点
     * 3)一条线和一个面穿越说明这条线的一部分(不是整条线)位于面内 4)g0只能是线类型几何，g1不能是点类型几何
     *
     * @param geo0 g0
     * @param geo1 g1
     * @return 如果穿越返回TRUE，否则返回FALSE
     */
    public static boolean IsCrosses(IGeometry geo0, IGeometry geo1)
      {
        //1)进行坐标投影,将两个几何体的坐标系投影到同一个坐标系统
        CoordinateSystem from = geo0.getCoordinateSystem();
        CoordinateSystem to = geo1.getCoordinateSystem();
        GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
        transformer.transform(geo0);
        //2)进行isCrosses判断
        boolean isCrosses = false;
        Object obj0 = geo0.getInternalObject();
        Object obj1 = geo1.getInternalObject();
        if ((obj0 instanceof mzGeometry) && (obj1 instanceof mzGeometry))
          {
            mzGeometry m_mzGeometry0 = (mzGeometry) obj0;
            mzGeometry m_mzGeometry1 = (mzGeometry) obj1;
            double dTolerance = m_mzGeometry0.getTolerance();
            isCrosses = mzSpatialAnylize.IsCrosses(m_mzGeometry0, m_mzGeometry1, dTolerance);
          }
        return isCrosses;
      }

    /**
     * 图形是否包含于(可以带边界)另一图形,g0是否包含于g1
     *
     * @param geo0 g0
     * @param geo1 g1
     * @return 如果被检测图形被包含(可以带边界)返回TRUE，否则返回FALSE
     */
    public static boolean IsWithin(IGeometry geo0, IGeometry geo1)
      {
        //1)进行坐标投影,将两个几何体的坐标系投影到同一个坐标系统
        CoordinateSystem from = geo0.getCoordinateSystem();
        CoordinateSystem to = geo1.getCoordinateSystem();
        GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
        transformer.transform(geo0);
        //2)进行IsWithin判断
        boolean isWithin = false;
        Object obj0 = geo0.getInternalObject();
        Object obj1 = geo1.getInternalObject();
        if ((obj0 instanceof mzGeometry) && (obj1 instanceof mzGeometry))
          {
            mzGeometry m_mzGeometry0 = (mzGeometry) obj0;
            mzGeometry m_mzGeometry1 = (mzGeometry) obj1;
            double dTolerance = m_mzGeometry0.getTolerance();
            isWithin = mzSpatialAnylize.IsWithin(m_mzGeometry0, m_mzGeometry1, dTolerance);
          }
        return isWithin;
      }

    /**
     * 是否有重叠部分,g0和g1是否重叠
     *
     * @param geo0 g0
     * @param geo1 g1
     * @return 如果有重叠部分返回TRUE，否则返回FALSE
     */
    public static boolean IsOverlaps(IGeometry geo0, IGeometry geo1)
      {
        //1)进行坐标投影,将两个几何体的坐标系投影到同一个坐标系统
        CoordinateSystem from = geo0.getCoordinateSystem();
        CoordinateSystem to = geo1.getCoordinateSystem();
        GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
        transformer.transform(geo0);
        //2）进行IsOverlaps判断
        boolean isOverlaps = false;
        Object obj0 = geo0.getInternalObject();
        Object obj1 = geo1.getInternalObject();
        if ((obj0 instanceof mzGeometry) && (obj1 instanceof mzGeometry))
          {
            mzGeometry m_mzGeometry0 = (mzGeometry) obj0;
            mzGeometry m_mzGeometry1 = (mzGeometry) obj1;
            double dTolerance = m_mzGeometry0.getTolerance();
            isOverlaps = mzSpatialAnylize.IsOverlaps(m_mzGeometry0, m_mzGeometry1, dTolerance);
          }
        return isOverlaps;
      }

    /**
     * 平移
     *
     * @param geo        要平移的几何
     * @param dDistanceX X轴上平移量
     * @param dDistanceY Y轴上平移量
     */
    public static void Move(IGeometry geo, double dDistanceX, double dDistanceY)
      {
        Object obj = geo.getInternalObject();
        if (obj instanceof mzGeometry)
          {
            mzGeometry m_mzGeometry0 = (mzGeometry) obj;
            mzSpatialAnylize.Move(m_mzGeometry0, dDistanceX, dDistanceY);
          }
      }

    /**
     * 旋转
     *
     * @param geo    要旋转的几何
     * @param x      旋转的中心x值
     * @param y      旋转的中心y值
     * @param dAngle 旋转的角度（单位：度）
     */
    public static void Rotate(IGeometry geo, double x, double y, double dAngle)
      {
        Object obj = geo.getInternalObject();
        if (obj instanceof mzGeometry)
          {
            mzGeometry m_mzGeometry0 = (mzGeometry) obj;
            mzSpatialAnylize.Rotate(m_mzGeometry0, x, y, dAngle);
          }
      }

    /**
     * 缩放
     *
     * @param geo     要缩放的几何
     * @param originx 缩放的中心x值
     * @param originy 缩放的中心y值
     * @param dSx     X轴的缩放值
     * @param dSy     Y轴的缩放值
     * @param asRadio 指定 #dSx和 #dSy是否是百分比
     */
    public static void Scale(IGeometry geo, double originx, double originy, double dSx, double dSy, boolean asRadio)
      {
        Object obj = geo.getInternalObject();
        if (obj instanceof mzGeometry)
          {
            mzGeometry m_mzGeometry0 = (mzGeometry) obj;
            mzSpatialAnylize.Scale(m_mzGeometry0, originx, originy, dSx, dSy, asRadio);
          }
      }

    /**
     * 镜像,求几何以point(x1，y1) 和 point(x2，y2) 为镜面的镜像
     *
     * @param geo 要求镜像的几何
     * @param x1  第一个点x值
     * @param y1  第一个点y值
     * @param x2  第二个点x值
     * @param y2  第二个点y值
     */
    public static void Mirror(IGeometry geo, double x1, double y1, double x2, double y2)
      {
        Object obj = geo.getInternalObject();
        if (obj instanceof mzGeometry)
          {
            mzGeometry m_mzGeometry0 = (mzGeometry) obj;
            mzSpatialAnylize.Mirror(m_mzGeometry0, x1, y1, x2, y2);
          }
      }

    /**
     * 串接
     *
     * @param geoConcatenateLineIn          传入参数，串接线
     * @param lstGeoSetIn                   传入参数，串接涉及的所有几何（面），需要串接的几何放在第一个位置
     * @param lstPolygonIDIn                传入参数，串接涉及的所有几何（面）ID，需要串接的几何放在第一个位置，
     *                                      并且这里的几何ID和第二个参数（lstGeoSetIn）中的几何一一对应
     * @param lstGeoSetOut                  传出参数，串接后的几何集
     * @param lstPolygonIDOut               传出参数，串接后的几何ID，和第四个参数中的几何集一一对应
     * @param lstArrDisputePolygonIDInfoOut 有争议的几何ID，列出了所有有争议的ID，并且列出了所有与该争议ID
     *                                      相关的几何ID，类似于一个二维数组。
     */
    public static void ConcatenatePolygon(IGeometry geoConcatenateLineIn, List<IGeometry> lstGeoSetIn, List<Integer> lstPolygonIDIn, List<IGeometry> lstGeoSetOut, List<Integer> lstPolygonIDOut, List<ArrayList> lstArrDisputePolygonIDInfoOut)
      {
        if (lstGeoSetIn.size() == 0)
          return;
        //如果为自相交的线，直接返回
        if (!geoConcatenateLineIn.isSimple())
          return;
        //一.进行坐标投影，将修边线的坐标系投影到面几何的坐标系
        CoordinateSystem from = geoConcatenateLineIn.getCoordinateSystem();
        CoordinateSystem to = from;
        if (lstGeoSetIn.size() > 0)
          {
            to = lstGeoSetIn.get(0).getCoordinateSystem();
          }
        if (!from.equals(to))
          {
            //串接线投影
            GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
            transformer.transform(geoConcatenateLineIn);
            //需要串接的所有几何面进行投影
            for (int i = 0; i < lstGeoSetIn.size(); i++)
              {
                IGeometry geo = lstGeoSetIn.get(i);
                from = geo.getCoordinateSystem();
                transformer = CoordinateSystem.getTransformer(from, to);
                transformer.transform(geo);
              }
          }
        //二.进行串接操作
        if (geoConcatenateLineIn == null || lstGeoSetIn == null || lstPolygonIDIn == null || lstGeoSetOut == null || lstPolygonIDOut == null || lstArrDisputePolygonIDInfoOut == null)
          return;
        Object objConcatenateLine = geoConcatenateLineIn.getInternalObject();
        mzGeometry pConcatenateLine = null;
        //1.获取串接线
        if (objConcatenateLine instanceof mzGeometry)
          {
            pConcatenateLine = (mzGeometry) objConcatenateLine;
          }
        //2.获取串接的几何集（多个多边形的几何）
        mzGeometrySet pGeoSet = new mzGeometrySet(true);
        for (int i = 0; i < lstGeoSetIn.size(); i++)
          {
            Object objGeo = lstGeoSetIn.get(i).getInternalObject();
            if (objGeo instanceof mzGeometry)
              {
                mzGeometry pGeo = (mzGeometry) objGeo;
                //克隆几何，底层创建的所有操作，不会影响传入的几何体
                mzGeometry pGeoClone = pGeo.clone();
                pGeoSet.AddGeometry(pGeoClone);
              }
          }
        //获取传入几何集的坐标系（以第一个几何为准）
        CoordinateSystem coordSystem = null;
        if (lstGeoSetIn.size() > 0)
          {
            IGeometry geo = lstGeoSetIn.get(0);
            coordSystem = geo.getCoordinateSystem();
          }
        //3.获取几何ID数组
        int[] arrPolygonIDIn = new int[lstPolygonIDIn.size()];
        for (int i = 0; i < lstPolygonIDIn.size(); i++)
          {
            arrPolygonIDIn[i] = lstPolygonIDIn.get(i);
          }
        //4.串接操作
        int[] arrPolygonIDOut = mzSpatialAnylize.ConcatenatePolygon(pConcatenateLine, pGeoSet, arrPolygonIDIn);
        //串接失败，直接返回
        if (arrPolygonIDOut == null || arrPolygonIDOut.length < 2)
          return;
        //对串接结果进行处理
        //lstGeoSetOut = new ArrayList<IGeometry>();
        //4.1）面几何集
        for (int i = 0; i < pGeoSet.GetGeometryCount(); i++)
          {
            mzGeometry pGeometry = pGeoSet.GetGeometry(i);
            if (pGeometry != null)
              {
                mzGeometry pGeoClone = pGeometry.clone();
                switch (pGeometry.getGeometryType())
                  {
                    case mzGeometry.mzGeometryPolygon: //单面
                      GeoPolygon geoPolygon = new GeoPolygon(coordSystem, (mzPolygon) pGeoClone);
                      lstGeoSetOut.add(geoPolygon);
                      break;
                    case mzGeometry.mzGeometryMultiPolygon: //多面
                      GeoMultiPolygon geoMultiPolygon = new GeoMultiPolygon(coordSystem, (mzMultiPolygon) pGeoClone);
                      lstGeoSetOut.add(geoMultiPolygon);
                      break;
                    default:
                  }
              }
          }
        //4.2)几何ID
        List<ArrayList> lstArrPolygonID = new ArrayList<ArrayList>();
        int nCount = arrPolygonIDOut[0];
        ArrayList<Integer> arrPolygonID = new ArrayList<Integer>();
        //将第一层解析（用-2分隔）
        for (int i = 0; i < nCount; i++)
          {
            if (arrPolygonIDOut[i] != -2)
              {
                arrPolygonID.add(arrPolygonIDOut[i]);
              }
            if (arrPolygonIDOut[i] == -2)
              {
                lstArrPolygonID.add(arrPolygonID);
                arrPolygonID = new ArrayList<Integer>();
              }
          }
        lstArrPolygonID.add(arrPolygonID);
        //串接后的多边形ID，和lstGeoSetOut中的几何一一对应
        for (int i = 0; i < lstArrPolygonID.get(1).size(); i++)
          {
            lstPolygonIDOut.add((Integer) lstArrPolygonID.get(1).get(i));
          }
        List<Integer> lstDisputePolygonID = lstArrPolygonID.get(2);
        //lstDisputePolygonIDInfoOut = new ArrayList<ArrayList>();
        //将第二层进行解析（用-1分隔）
        ArrayList arrEachDisputePolygonID = new ArrayList<Integer>();
        for (int i = 0; i < lstDisputePolygonID.size(); i++)
          {
            if (lstDisputePolygonID.get(i) != -1)
              {
                arrEachDisputePolygonID.add(lstDisputePolygonID.get(i));
              }
            if (lstDisputePolygonID.get(i) == -1)
              {
                lstArrDisputePolygonIDInfoOut.add(arrEachDisputePolygonID);
                arrEachDisputePolygonID = new ArrayList<Integer>();
              }
          }
      }

    //解析自相交处理后的几何
    private static void AnalysizeSimplifyedGeometry(List<IGeometry> lstGeo, mzGeometry mzGeo)
      {
        if (lstGeo == null || mzGeo == null)
          return;
        int nGeoType = mzGeo.getGeometryType();
        switch (nGeoType)
          {
            // 几何为空
            case mzGeometry.mzGeometryNull:
              break;
            // 单点
            case mzGeometry.mzGeometryPoint:
            {
              IGeometry geometry = new GeoPoint(CoordinateSystem.create(mzGeo.getSrid()), (mzPoint) mzGeo);
              lstGeo.add(geometry);
            }
            break;
            // 多点
            case mzGeometry.mzGeometryMultiPoint:
            {
              IGeometry geometry = new GeoMultiPoint(CoordinateSystem.create(mzGeo.getSrid()), (mzMultiPoint) mzGeo);
              lstGeo.add(geometry);
            }
            break;
            // 连续线/混合
            case mzGeometry.mzGeometryPath:
            {
              IGeometry geometry = new GeoLine(CoordinateSystem.create(mzGeo.getSrid()), (mzPath) mzGeo);
              lstGeo.add(geometry);
            }
            break;
            // 环(Ring)
            case mzGeometry.mzGeometryRing:
              break;
            // 多段线
            case mzGeometry.mzGeometryMultiPath:
            {
              mzMultiLineString m_multiLineString = (mzMultiLineString) mzGeo;
              int nPathCount = m_multiLineString.getPathCount();
              for (int i = 0; i < nPathCount; i++)
                {
                  mzPath m_mzPath = m_multiLineString.GetPath(i);
                  IGeometry geometry = new GeoLine(CoordinateSystem.create(m_mzPath.getSrid()), m_mzPath);
                  lstGeo.add(geometry);
                }
            }
            break;
            // 单面
            case mzGeometry.mzGeometryPolygon:
            {
              IGeometry geometry = new GeoPolygon(CoordinateSystem.create(mzGeo.getSrid()), (mzPolygon) mzGeo);
              lstGeo.add(geometry);
            }
            break;
            // 多面
            case mzGeometry.mzGeometryMultiPolygon:
            {
              mzMultiPolygon m_multiPolygon = (mzMultiPolygon) mzGeo;
              int nPolygonCount = m_multiPolygon.getPolygonCount();
              for (int i = 0; i < nPolygonCount; i++)
                {
                  mzPolygon m_mzPolygon = m_multiPolygon.GetPolygon(i);
                  IGeometry geometry = new GeoPolygon(CoordinateSystem.create(m_mzPolygon.getSrid()), m_mzPolygon);
                  lstGeo.add(geometry);
                }
            }
            break;
            // 正矩形(Eenvelope)
            case mzGeometry.mzGeometryEnvelope:
              break;
            // 默认情况
            default:
              break;
          }

      }

    //将有自相交的几何进行打散
    public static List<IGeometry> Simplify(IGeometry geo)
      {
        List<IGeometry> lstGeo = new ArrayList<>();
        mzGeometry m_mzGeo = (mzGeometry) geo.getInternalObject();
        //1)面未自相交
        if (m_mzGeo.IsSimple())
          {
            lstGeo.add(geo);
            return lstGeo;
          } else //2)有自相交，将几何对象打散
        {
          mzGeometry m_mzGeoResult = mzSpatialAnylize.Simplify(m_mzGeo);
          AnalysizeSimplifyedGeometry(lstGeo, m_mzGeoResult);
          return lstGeo;
        }
      }

    //将有自相交的几何进行打散
    public static List<IGeometry> simplify(IGeometry geo)
      {
        List<IGeometry> lstGeo = new ArrayList<>();
        mzGeometry m_mzGeo = (mzGeometry) geo.getInternalObject();
        //        //1)面未自相交
        //        if (m_mzGeo.IsSimple())
        //          {
        //            lstGeo.add(geo);
        //            return lstGeo;
        //          } else //2)有自相交，将几何对象打散
        {
          mzGeometry m_mzGeoResult = mzSpatialAnylize.Simplify(m_mzGeo);
          AnalysizeSimplifyedGeometry(lstGeo, m_mzGeoResult);
          return lstGeo;
        }
      }

    //捕捉功能
    public static HitInfos HitTest(IGeometry geo, GeoPoint geoPoint, double tolerance, int mode)
      {
        mzGeometry m_mzGeo = (mzGeometry) geo.getInternalObject();
        CoordinateSystem from = geoPoint.getCoordinateSystem();
        CoordinateSystem to = geo.getCoordinateSystem();
        GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
        transformer.transform(geoPoint);
        //获取捕捉点
        mzPoint m_mzPoint = new mzPoint();
        m_mzPoint.setSrid(geo.getCoordinateSystem().getSrid());
        m_mzPoint.setX(geoPoint.getX());
        m_mzPoint.setY(geoPoint.getY());
        mzHitInfos mzHitInfos = mzSpatialAnylize.HitTest(m_mzGeo, m_mzPoint, tolerance, mode);
        return new HitInfos(mzHitInfos);
      }
  }
